package com.sgb.link.utils;

import android.content.Context;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import com.sgb.link.api.CommonNet;
import com.sgb.link.api.LogisticsNet;
import com.sgb.link.cachemarker.CacheMarker;
import com.sgb.link.entity.AMapAddressEntity;
import com.swgk.core.base.api.ICallBack;
import com.swgk.core.base.model.entity.BaseEntity;
import com.swgk.core.mmkvutil.MkvUtils;
import com.swgk.core.mmkvutil.DatalUtils;
import com.swgk.core.util.NumberUtil;
import com.swgk.core.util.SharedPreferenceUtil;
import com.swgk.core.view.areapopup.AddressEntity;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * @author: 杨畔
 * @date: 2021/2/6 12:27
 * @Description: 地址帮助类，获取省市区地址并缓存，常用地址使用方法
 */
public class AddressHelper {
    //原始数据
    private List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>> mAreaList = new ArrayList<>();
    // 一级联动数据
    private final List<AddressEntity> mProvinceList = new ArrayList<>();
    // 二级联动数据
    private final List<List<AddressEntity>> mCityList = new ArrayList<>();
    // 三级联动数据
    private final List<List<List<AddressEntity>>> mDistrictList = new ArrayList<>();
    //
    private Gson mGson = new Gson();

    private AddressHelper() {
    }

    private static class Single {
        private final static AddressHelper instance = new AddressHelper();
    }

    public static AddressHelper getInstance() {
        return Single.instance;
    }

    /**
     * 获取地址信息回调
     */
    public interface CallBack {
        //初始数据
        void initialData(List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>> data);

        //三级数据
        void threeData(List<AddressEntity> provinceList, List<List<AddressEntity>> cityList, List<List<List<AddressEntity>>> districtList);
    }

    public static abstract class AddressCallBack implements CallBack {
        @Override
        public void initialData(List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>> data) {

        }

        @Override
        public void threeData(List<AddressEntity> provinceList, List<List<AddressEntity>> cityList, List<List<List<AddressEntity>>> districtList) {

        }
    }

    /**
     * 获取当前定位回调
     */
    public interface LocationCallBack {
        void location(AMapAddressEntity entity);
    }

    /**
     * 更新省市区信息
     */
    public void updateAllArea(List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>> data) {
        if (data == null || data.size() == 0) return;
        //保存原始数据
        mAreaList.clear();
        mAreaList.addAll(data);
        //设置二三级数据
        mProvinceList.clear();
        mCityList.clear();
        mDistrictList.clear();
        for (AddressEntity<List<AddressEntity<List<AddressEntity>>>> pro : data) {
            //一级列表
            mProvinceList.add(pro);
            //二级列表
            List<AddressEntity> cityList = new ArrayList<>(pro.getChildren());
            mCityList.add(cityList);
            //三级列表
            List<List<AddressEntity>> areaList = new ArrayList<>();
            for (AddressEntity<List<AddressEntity>> area : pro.getChildren()) {
                if (area.getChildren() == null) continue;
                areaList.add(area.getChildren());
            }
            mDistrictList.add(areaList);
        }
    }

    /**
     * 获取所有地址
     */
    public void getAllArea(CallBack callBack) {
        if (callBack == null) return;
        if (mAreaList != null && mAreaList.size() > 0) {
            dealData(callBack);
        } else {
            getAllAreaList(callBack);
        }

    }

    /**
     * 获取省市区数据
     */
    private void getAllAreaList(CallBack callBack) {
        Type type = new TypeToken<List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>>>() {}.getType();
        Object obj = DatalUtils.getInstance().getData(MkvUtils.CacheModular, CacheMarker.TRANSPORT_AREA_DATA, type);
        if (obj != null){
            List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>> dataList = (List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>>) obj;
            updateAllArea(dataList);
            dealData(callBack);
        }else {
            LogisticsNet.getInstance().getService().getCityList().enqueue(new ICallBack<BaseEntity<List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>>>>() {
                @Override
                public void onSuccess(BaseEntity<List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>>> data) {
                    if (data.getData() == null)  return;
                    DatalUtils.getInstance().putData(MkvUtils.CacheModular, CacheMarker.TRANSPORT_AREA_DATA, data.getData());
                    updateAllArea(data.getData());
                    dealData(callBack);
                }

                @Override
                public void onFailure(Call<BaseEntity<List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>>>> call, Throwable t) {
                    dealData(callBack);
                }
            });

        }
    }

    /**
     * 统一处理数据，防止浅拷贝数据错乱
     */
    private void dealData(CallBack callBack) {
        //转换json字符串，再转新数组，深拷贝数据，防止数据错乱
        String areaStr = mGson.toJson(mAreaList);
        String provinceStr = mGson.toJson(mProvinceList);
        String cityStr = mGson.toJson(mCityList);
        String districtStr = mGson.toJson(mDistrictList);
        //原始数据
        List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>> areaList = mGson.fromJson(areaStr, new TypeToken<List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>>>() {
        }.getType());
        // 一级联动数据
        List<AddressEntity> provinceList = mGson.fromJson(provinceStr, new TypeToken<List<AddressEntity>>() {
        }.getType());
        // 二级联动数据
        List<List<AddressEntity>> cityList = mGson.fromJson(cityStr, new TypeToken<List<List<AddressEntity>>>() {
        }.getType());
        // 三级联动数据
        List<List<List<AddressEntity>>> districtList = mGson.fromJson(districtStr, new TypeToken<List<List<List<AddressEntity>>>>() {
        }.getType());
        //回调数据
        callBack.initialData(areaList);
        callBack.threeData(provinceList, cityList, districtList);
    }

    /**
     * 查找省市区编码
     */
    public void findCode(AMapAddressEntity entity) {
        AddressEntity[] code = findCode(entity.getProvince(), entity.getCity(), entity.getDistrict());
        if (code != null && code.length >= 3) {
            //设置省市区简称no
            if (code[0] != null) {
                entity.setProvinceNo(code[0].getNo());
                entity.setProvince(code[0].getSimpleName());
                entity.setAllProvince(code[0].getName());
            }
            if (code[1] != null) {
                entity.setCityNo(code[1].getNo());
                entity.setCity(code[1].getSimpleName());
                entity.setAllCity(code[1].getName());
            }
            if (code[2] != null) {
                entity.setDistrictNo(code[2].getNo());
                entity.setDistrict(code[2].getSimpleName());
                entity.setAllDistrict(code[2].getName());
            }
        }
    }

    /**
     * 查找省市区编码
     *
     * @param provinceStr 省名称
     * @param cityStr     市名称
     * @param districtStr 区名称
     * @return 长度为3的省市区地址对象数组，0：省，1：市，2：区，都可能为null
     */
    public AddressEntity[] findCode(String provinceStr, String cityStr, String districtStr) {
        //省市区弹窗选中位置
        AddressEntity[] code = new AddressEntity[3];
        String selectProvince = provinceStr;
        //针对特殊省处理
        if (!TextUtils.isEmpty(selectProvince)) {
            if (selectProvince.contains("台湾")) {
                //针对特殊省处理
                selectProvince = "台湾";
            } else if (selectProvince.endsWith("市")) {
                //针对直辖市处理(适应接口)
                selectProvince = selectProvince.substring(0, selectProvince.length() - 1);
            }
        }
        //查找省position
        for (AddressEntity entity : mProvinceList) {
            if (entity.getName().contains(selectProvince)) {
                //设置省编码
                entity.setIndex(mProvinceList.indexOf(entity));
                code[0] = entity;
                break;
            }
        }
        //查找市position
        if (code[0] != null && code[0].getIndex() < mCityList.size()) {
            List<AddressEntity> cityList = mCityList.get(code[0].getIndex());
            for (AddressEntity entity : cityList) {
                if (entity.getName().contains(cityStr)) {
                    //设置城市编码
                    entity.setIndex(cityList.indexOf(entity));
                    code[1] = entity;
                    break;
                }
            }
        }
        //查找区position
        if (code[0] != null && code[1] != null
                && code[0].getIndex() < mDistrictList.size()
                && code[1].getIndex() < mDistrictList.get(code[0].getIndex()).size()) {
            if (districtStr.endsWith("市") || districtStr.endsWith("县") || districtStr.endsWith("区")) {
                districtStr = districtStr.substring(0, districtStr.length() - 1);
            }
            List<AddressEntity> districtList = mDistrictList.get(code[0].getIndex()).get(code[1].getIndex());
            for (AddressEntity entity : districtList) {
                if (entity.getName().contains(districtStr)) {
                    //设置区域编码
                    entity.setIndex(districtList.indexOf(entity));
                    code[2] = entity;
                    break;
                }
            }
        }
        return code;
    }

    /**
     * 获取当前定位信息
     */
    public void getCurrentLocation(Context context, LocationCallBack callBack) {
        if (callBack == null) return;
        getAllArea(new AddressCallBack() {
            @Override
            public void initialData(List<AddressEntity<List<AddressEntity<List<AddressEntity>>>>> data) {
                if (data == null) {
                    callBack.location(null);
                    return;
                }
                setSendLocation(context, callBack);
            }
        });
    }

    /**
     * 设置定位信息
     */
    private void setSendLocation(Context context, LocationCallBack callBack) {
        if (callBack == null) return;
        AMapAddressEntity entity = new AMapAddressEntity();
        //查找地址下标
        if (LocationUtil.isOpenLocation(context)) {
            //设置经纬度
            double lat = NumberUtil.convertToDouble(SharedPreferenceUtil.getInstance().getString(SharedPreferenceUtil.LATITUDE_ID, "0"));
            double log = NumberUtil.convertToDouble(SharedPreferenceUtil.getInstance().getString(SharedPreferenceUtil.LONGITUDE_ID, "0"));
            if (lat != 0 && log != 0) {
                entity.setLongitude(log);
                entity.setLatitude(lat);
            } else {
                //未获取定位数据时不填入默认信息
                callBack.location(null);
                return;
            }
            //查找省市区no
            String provinceName = SharedPreferenceUtil.getInstance().getSaveStringData(SharedPreferenceUtil.Province, "新疆");
            String cityName = SharedPreferenceUtil.getInstance().getSaveStringData(SharedPreferenceUtil.City, "乌鲁木齐");
            String areaName = SharedPreferenceUtil.getInstance().getSaveStringData(SharedPreferenceUtil.Area, "天山");
            String address = SharedPreferenceUtil.getInstance().getSaveStringData(SharedPreferenceUtil.AoiName, "");
            AddressEntity[] code = AddressHelper.getInstance().findCode(provinceName, cityName, areaName);
            if (code != null && code.length >= 3) {
                //设置省市区简称no
                if (code[0] != null) {
                    entity.setProvinceNo(code[0].getNo());
                    entity.setProvince(code[0].getSimpleName());
                }
                if (code[1] != null) {
                    entity.setCityNo(code[1].getNo());
                    entity.setCity(code[1].getSimpleName());
                }
                if (code[2] != null) {
                    entity.setDistrictNo(code[2].getNo());
                    entity.setDistrict(code[2].getSimpleName());
                }
            }
            entity.setSnippet(address);
            callBack.location(entity);
        } else {
            callBack.location(null);
        }
    }
}
